- /* sifiisub.cpp by K.Tsuru */
- // function ID = 422 BRADIX
- // bugfix in version 2.16
- /******************************************
- SInteger class
- It provides the subtraction result = m - n.
- ******************************************/
- #ifndef SN_H
- #include "sn.h"
- #endif
-
- void IISub(const SInteger& m, const SInteger& n, SInteger& result){
- int sgn = m.Sign(422) * n.Sign(422), c;
- if(!sgn){
- if(!m.Sign()){ // m = 0
- result = n; result.ChangeSign(); // result = 0 - n;
- } else result = m; // result = m - 0;
- return;
- } else if(sgn < 0){ //different sign m - n = m + (-n)
- // Notice the case "&result == &m" or "&result == &n".
- SInteger temp(n); // bugfix ver. 2.16 on Jul 31, 2002
- temp.ChangeSign(); // temp = -n
-
- IIAdd(m, temp, result); //The sign is the same as that of m and set in IIAdd().
- return;
- }
-
- // Here m and n have the same sign.
- c = LLCompare(m, n);
- sgn = m.Sign();
-
- if(c < 0){ // |n| > |m|, m-n = -(n-m)
- IISub(n, m, result); result.ChangeSign(); return;
- } else if(!c){ //same value m == n
- result.SetZero(); return;
- }
- // Here |m| > |n| ("c > 0 && mh >= nh") and evaluate m - n.
- // m and n have the same sign and the figures of m is greater than or equal to that of n.
- if(n.aHead == 0){ // n has one figure.
- // bugfix ver. 2.16
- if(n.Sign() > 0) IsSub(m, n(0), result); // 0 < n < m, m - n = m - n(0)
- else IsAdd(m, n(0), result); // m < n < 0, m - n = m + n(0)
-
- result.SetSign(sgn);
- return;
- }
- uint mh = m.Head(), nh = n.Head();
- uint rt = min( m.Tail(), n.Tail() );
- #ifndef NDEBUG
- assert(mh >= nh);
- #endif
- /*
- Neither IISub(L, z, L); nor IISub(z, L, L);
- it allocates the memory of "result" and initializes it.
- */
- if( (&m != &result) && (&n != &result) ){
- result.valloc(m.Size(), -1);
- if(rt) result.figure.clear(0, rt -1u);
- result.figure.clear(mh+1u);
- } else result.Reserve(mh); // IISub(z, L, L); z > L(=result)
-
- const fType* mv = m.ReadFigures();
- const fType* nv = n.ReadFigures();
- fType* rv = result.figure.Elements();
- #ifndef NDEBUG
- result.figure(mh);
- #endif
-
- // mh >= nh
- uint i;
- fType u = 0; //borrow from upper figure, 0 or 1
- for(i = rt; i <= nh; i++) {
- u = mv[i] - nv[i] - u;
- rv[i] = u & BRADIX1;
- //u = (u & BRADIX) ? 1 : 0;
- u = u >> BRADIX_BITS; // 0 or 1
- }
- //processing upper figures
- for( ; u && (i <= mh) ; i++) {
- //The borrow is non-zero.
- u = mv[i] - u;
- rv[i] = u & BRADIX1;
- //u = (u & BRADIX) ? 1 : 0;
- u = u >> BRADIX_BITS;
- }
- #ifndef NDEBUG
- assert(u == 0);
- #endif
- if((mh >= i) && (rv != mv) ){ //no borrw (u = 0)
- memcpy(rv + i, mv + i, sizeof(fType)*(mh-i+1u));
- // while(i <= mh){ rv[i] = mv[i]; i++; }
- }
- //It gets the figure positions.
- while( !rv[rt] ) rt++;
- while( !rv[mh] ) mh--;
- result.aHead = mh;
- result.aTail = rt;
- result.SetSign(sgn);
- //If the figures decrease it reduces the size.
- if( 2u*(result.aHead+1) <= result.figure.size() ) result.DoCutDown();
- }
-
sifiisub.cpp : last modifiled at 2017/03/13 14:31:59(2,989 bytes)
created at 2016/04/25 14:53:17
The creation time of this html file is 2017/10/25 11:09:45 (Wed Oct 25 11:09:45 2017).